package com.xmut.xmutbackend.Interceptor;

import com.alibaba.fastjson.JSONObject;
import com.xmut.xmutbackend.entity.Result;
import com.xmut.xmutbackend.service.IOperationLogService;
import com.xmut.xmutbackend.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Component
public class LoginCheckInterceptor implements HandlerInterceptor {

    @Autowired
    private IOperationLogService logService;

    //前置方式
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器检查URL: " + request.getRequestURI());
        
        //1.获取请求url
        String requestURI = request.getRequestURI();
        //某些接口不需要登录验证，如果已在WebConfig中配置，这里不需要重复判断
        
        //3.获取请求头中的令牌（token）- 支持多种获取方式
        String token = getTokenFromRequest(request);
        
        System.out.println("获取到的token: " + (token != null ? "长度" + token.length() : "null"));

        //4.判断令牌是否存在，如果不存在，返回错误结果（未登录）
        if(!StringUtils.hasLength(token)){
            System.out.println("未提供token，拒绝访问: " + requestURI);
            //创建响应结果对象
            Result responseResult = Result.fail("NOT_LOGIN");
            //把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
            String json = JSONObject.toJSONString(responseResult);
            //设置响应头（告知浏览器：响应的数据类型为json、响应的数据编码表为utf-8）
            response.setContentType("application/json;charset=utf-8");
            //响应
            response.getWriter().write(json);

            return false;//不放行
        }

        //5.解析token，如果解析失败，返回错误结果（未登录）
        try {
            JwtUtils.parseJWT(token);
            System.out.println("Token验证通过，允许访问: " + requestURI);
        } catch (ExpiredJwtException e) {
            System.out.println("Token已过期: " + requestURI);
            //创建响应结果对象
            Result responseResult = Result.fail("TOKEN_EXPIRED");
            //把Result对象转换为JSON格式字符串
            String json = JSONObject.toJSONString(responseResult);
            //设置响应头
            response.setContentType("application/json;charset=utf-8");
            //响应
            response.getWriter().write(json);
            return false;
        } catch (Exception e){
            System.out.println("Token无效: " + requestURI + ", 错误: " + e.getMessage());
            //创建响应结果对象
            Result responseResult = Result.fail("INVALID_TOKEN");
            //把Result对象转换为JSON格式字符串
            String json = JSONObject.toJSONString(responseResult);
            //设置响应头
            response.setContentType("application/json;charset=utf-8");
            //响应
            response.getWriter().write(json);
            return false;
        }

        // 存储token到请求属性中，供afterCompletion使用
        request.setAttribute("userToken", token);
        //6.放行
        return true;
    }

    /**
     * 从请求中获取token，支持多种方式
     */
    private String getTokenFromRequest(HttpServletRequest request) {
        // 1. 从标准Authorization头获取Bearer token
        String authHeader = request.getHeader("Authorization");
        if (StringUtils.hasLength(authHeader) && authHeader.startsWith("Bearer ")) {
            return authHeader.substring(7); // 去掉"Bearer "前缀
        }
        
        // 2. 从自定义token头获取
        String tokenHeader = request.getHeader("token");
        if (StringUtils.hasLength(tokenHeader)) {
            return tokenHeader;
        }
        
        // 3. 从请求参数获取
        String tokenParam = request.getParameter("token");
        if (StringUtils.hasLength(tokenParam)) {
            return tokenParam;
        }
        
        return null;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 获取请求开始时保存的token
        String token = (String) request.getAttribute("userToken");
        if (StringUtils.hasLength(token)) {
            try {
                // 尝试解析token
                Claims claims = JwtUtils.parseJWT(token);
                Long userId = Long.valueOf(claims.get("id").toString());
                String username = claims.get("username").toString();

                // 记录操作日志
                logService.recordLog(userId, username, request.getMethod(), request.getRequestURI(), getClientIp(request), 1);
            } catch (ExpiredJwtException e) {
                // 从过期的JWT中提取用户信息
                Claims claims = e.getClaims();
                if (claims != null) {
                    Long userId = Long.valueOf(claims.get("id").toString());
                    String username = claims.get("username").toString();
                    // 记录操作日志，但标记为过期
                    logService.recordLog(userId, username, request.getMethod(), request.getRequestURI(), getClientIp(request), 0);
                }
            } catch (Exception e) {
                logService.recordLog(null, "Token无效", request.getMethod(), request.getRequestURI(), getClientIp(request), 0);
            }
        }
    }

    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}
